//
//  ColorPickerViewController.swift
//  PorscheRegistration
//
//  Created by Jinzhu Liu on 2023/11/18.
//

import UIKit
import Combine

class ColorPickerViewController: UIViewController, UINavigationControllerDelegate {
    
    struct Constant {
        static let unknowCellIdentifier = "UnknowType"
    }
    
    typealias DataSource = UITableViewDiffableDataSource<Section, RowItem>
    typealias Snapshot = NSDiffableDataSourceSnapshot<Section, RowItem>

    var viewModel: ColorPickerViewModelType
    
    private var rowItemList: [RowItem] = []
    private var cancellable = Set<AnyCancellable>()
    private lazy var dataSource = makeDataSource()
    var tableView: UITableView?
    
    init(viewModel: ColorPickerViewModelType) {
        self.viewModel = viewModel
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        setupUI()
        setupLayouts()

        viewModel.output.updateColorItemsPublisher
            .sink { [unowned self] cellViewModels in
                self.generateRowItems(with: cellViewModels)
                self.applySnapshot()
            }.store(in: &cancellable)
        
        viewModel.output.dismissPublisher
            .sink { [unowned self] _ in
                self.dismiss(animated: true)
            }.store(in: &cancellable)
        viewModel.input.start()
        
        applySnapshot(animatingDifferences: false)
    }
    
    private func generateRowItems(with cellViewModels: [ColorPickerCellViewModelType]) {
        var rowItems = [RowItem]()
        for (index, cellViewModel) in cellViewModels.enumerated() {
            rowItems.append(RowItem(id: index, viewModel: cellViewModel as AnyObject))
        }
        self.rowItemList = rowItems
    }
    
    private func applySnapshot(animatingDifferences: Bool = true) {
        guard let dataSource else { return }
        
        var snapshot = Snapshot()
        snapshot.appendSections([.main])
        snapshot.appendItems(rowItemList)
        dataSource.apply(snapshot, animatingDifferences: animatingDifferences)
    }
        
    private func setupUI() {
        self.view.backgroundColor = .systemGroupedBackground
        let tableView = UITableView(frame: .zero, style: .grouped)
        tableView.backgroundColor = .clear
        tableView.estimatedRowHeight = 52.0
        tableView.delegate = self
        
        self.view.addSubview(tableView)
        
        tableView.register(ColorPickerCell.self, forCellReuseIdentifier: ColorPickerCell.reuseIdentifier)
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: Constant.unknowCellIdentifier)
        
        self.tableView = tableView
    }
    
    private func setupLayouts() {
        guard let tableView else { return }
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor).isActive = true
        tableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
        tableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true

    }
 
    func makeDataSource() -> DataSource? {
        
        guard let tableView else { return nil }
 
        let dataSource = DataSource(tableView: tableView) { tableView, indexPath, item in
            var cell: UITableViewCell?
            let cellViewModel = item.viewModel
            switch cellViewModel {
            case is any ColorPickerCellViewModelType:
                cell = tableView.dequeueReusableCell(withIdentifier: ColorPickerCell.reuseIdentifier, for: indexPath)
            default:
                cell = tableView.dequeueReusableCell(withIdentifier: Constant.unknowCellIdentifier, for: indexPath)
            }
            cell?.selectionStyle = .none
            if cell is ColorPickerCell {
                (cell as! ColorPickerCell).update(with: cellViewModel)
            }
            
            return cell
        }
        
        return dataSource
    }
    
}

extension ColorPickerViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: false)
        
        let rowItem = rowItemList[indexPath.row]
        if let cellViewModel = rowItem.viewModel as? ColorPickerCellViewModelType {
            self.viewModel.input.selected(item: cellViewModel)
        }
        
    }
}
